package dj.dwr;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;
import org.directwebremoting.Browser;
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.ScriptSessionFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.google.gson.GsonBuilder;

import dj.Constant;
import dj.listener.DwrScriptSessionManagerUtil;
import dj.model.Friend;
import dj.model.FriendExtend;
import dj.model.FriendGroup;
import dj.model.Tuser;
import dj.pageModel.PtalkContext;
import dj.pageModel.Puser;
import dj.pageModel.TreeNode;
import dj.service.FriendService;
import dj.service.TalkContextService;
import dj.service.UserService;

@Repository("messagePush")
public class MessagePush {

	// 消息堆栈，外层Map userid为key,里层map 消息id为key,根据用户和消息id可获得某一条消息
	private static Map<String, Map<String, PtalkContext>> userMessage = new LinkedHashMap<String, Map<String, PtalkContext>>();

	private UserService userService;

	private FriendService friendService;

	private TalkContextService tcs;

	public UserService getUserService() {
		return userService;
	}

	@Autowired
	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public FriendService getFriendService() {
		return friendService;
	}

	@Autowired
	public void setFriendService(FriendService friendService) {
		this.friendService = friendService;
	}

	public TalkContextService getTcs() {
		return tcs;
	}

	@Autowired
	public void setTcs(TalkContextService tcs) {
		this.tcs = tcs;
	}

	/**
	 * 初始化DwrScriptSessionManagerUtil
	 */
	public void onPageLoad() {

		DwrScriptSessionManagerUtil dwrScriptSessionManagerUtil = new DwrScriptSessionManagerUtil();

		try {
			// 初始化dwr用户监听
			dwrScriptSessionManagerUtil.init();

		} catch (ServletException e) {

			e.printStackTrace();

		}

	}
	
	public void sendMsgToUser(HttpSession session, final String msg, final String fn) {
		final Puser sessionInfo = (Puser) session.getAttribute(Constant.USER_SESSION);

		if (null != sessionInfo) {

				Browser.withAllSessionsFiltered(new ScriptSessionFilter() {

					public boolean match(ScriptSession session) {

						if (session.getAttribute("userId") == null)

							return false;

						else 
							
							return sessionInfo.getId().equals(session.getAttribute("userId"));
					}

				}, new Runnable() {

					public void run() {

						Collection<ScriptSession> sessions = Browser.getTargetSessions();

						for (ScriptSession scriptSession : sessions) {
							
							ScriptBuffer script = new ScriptBuffer();
							
							script.appendCall("showSysMsg", msg, fn);

							scriptSession.addScript(script);

						}

					}

				});
		} else {
			UpdatePageInfo.callScript("index.jsp", "noSession");
		}
	}

	/**
	 * 用户登录后，更新好友状态
	 */
	public void updateFriendState(final boolean state) {
		final Puser sessionInfo = (Puser) ServletActionContext.getRequest().getSession().getAttribute(Constant.USER_SESSION);

		if (null != sessionInfo) {
			// 所有有起好友的人
			List<Friend> friends = friendService.getHasFriendList(sessionInfo);
			// 所有好友用户id，推送比较id用
			final List<String> friendIds = new ArrayList<String>();

			if(null != friends) {
				
				for (Friend friend : friends) {
					// 有其好友用户id
					friendIds.add(friend.getUserid());
				}

				Browser.withAllSessionsFiltered(new ScriptSessionFilter() {

					public boolean match(ScriptSession session) {

						if (session.getAttribute("userId") == null)

							return false;

						else 
							
							return friendIds.contains(session.getAttribute("userId"));
					}

				}, new Runnable() {

					public void run() {

						Collection<ScriptSession> sessions = Browser.getTargetSessions();

						for (ScriptSession scriptSession : sessions) {
							
							ScriptBuffer script = new ScriptBuffer();
							
							Friend friend = friendService.getFriend((String) scriptSession.getAttribute("userId"), sessionInfo.getId());
							
							TreeNode treeNode = friendService.getFriendNode(friend);
							//如果是登录，图标改为在线图标，否则改为离线图标
							if(state) {
								treeNode.setIconCls("icon-user");
								treeNode.getAttributes().put("online", true);
							} else {
								treeNode.setIconCls("tree-node");
								treeNode.getAttributes().put("online", false);
							}
							
							script.appendCall("updateFriendState", new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(treeNode));

							scriptSession.addScript(script);

						}

					}

				});
			}
		} else {
			UpdatePageInfo.callScript("index.jsp", "noSession");
		}
	}

	/**
	 * 点对点发送消息
	 * 
	 * @param userid
	 * @param message
	 */
	public void sendMessageAuto(String userid, String friendid, String message) {

		final String friendId = friendid;

		final String userId = userid;

		final String autoMessage = message;
		Puser sessionInfo = (Puser) ServletActionContext.getRequest().getSession().getAttribute(Constant.USER_SESSION);
		if (null != sessionInfo) {

			final PtalkContext ti = setTalkItem(userId, friendId, autoMessage);

			Browser.withAllSessionsFiltered(new ScriptSessionFilter() {

				public boolean match(ScriptSession session) {
					
					if (session.getAttribute("userId") == null)

						return false;

					else
						
						return (session.getAttribute("userId")).equals(friendId);

				}

			}, new Runnable() {

				private ScriptBuffer script = new ScriptBuffer();

				public void run() {

					script.appendCall("showMessage", new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(ti), false);

					Collection<ScriptSession> sessions = Browser.getTargetSessions();

					for (ScriptSession scriptSession : sessions) {

						scriptSession.addScript(script);

					}

				}

			});
		} else {
			UpdatePageInfo.callScript("index.jsp", "noSession");
		}

	}

	/**
	 * 获取消息List
	 * 
	 * @return
	 */
	public static Map<String, Map<String, PtalkContext>> getUserMessage() {
		return userMessage;
	}

	/**
	 * 把一条消息放到消息list中
	 * 
	 * @param userid
	 *            用户id
	 * @param friendid
	 *            接收人id
	 * @param msg
	 *            消息
	 */
	public PtalkContext setTalkItem(String userid, String friendid, String msg) {
		// 发送人
		Tuser user = userService.getUserById(userid);
		// 接收人
		Tuser friend = userService.getUserById(friendid);
		List<FriendGroup> fgls = friendService.getFriendGroup(friendid);

		PtalkContext ti = new PtalkContext();
		ti.setId(UUID.randomUUID().toString());
		ti.setReceiveUserid(friendid);
		ti.setReceiveUsername(friend.getName());
		ti.setFgls(fgls);
		ti.setSendUserid(userid);
		ti.setSendTime(new Date());
		ti.setRead(false);
		ti.setMsg(msg);

		// 判断发送人是否在接收人好友中，如果不在 则加到接收人的陌生人组中
		Friend f = friendService.getFriend(friendid, userid);
		// 备注名称
		String remarkName = "";
		if (null == f) {
			f = new Friend();
			f.setId(UUID.randomUUID().toString());
			f.setUserid(friendid);
			f.setTuser(user);
			FriendGroup mfg = new FriendGroup();
			for (FriendGroup fg : Constant.COMMON_FRIENDGROUP) {
				// 1为陌生人组id,固定不变
				if ("1".equals(fg.getId())) {
					mfg = fg;
					break;
				}
			}
			f.setGroupid(mfg.getId());
			friendService.saveFriend(f);
			ti.setReloadGroup(mfg);
		} else {
			if (null != f.getFriendExtends() && f.getFriendExtends().size() > 0) {
				FriendExtend fe = f.getFriendExtends().iterator().next();
				remarkName = fe.getRemarkName();
			}
		}

		String friendName = "";
		if ("".equals(remarkName)) {
			if (null != f.getTuser().getDisplayName() && !"".equals(f.getTuser().getDisplayName().trim())) {
				friendName = f.getTuser().getDisplayName() + "(" + f.getTuser().getName() + ")";
			} else {
				friendName = f.getTuser().getName();
			}
		} else {
			friendName = remarkName + "(" + f.getTuser().getName() + ")";
		}
		ti.setSendUsername(friendName);

		// 消息存到数据库
		tcs.saveContextToDb(ti);

		// 未读消息放到接收人消息栈中
		if (null != userMessage.get(friendid)) {
			userMessage.get(friendid).put(ti.getId(), ti);
		} else {
			Map<String, PtalkContext> tils = new LinkedHashMap<String, PtalkContext>();
			tils.put(ti.getId(), ti);
			userMessage.put(friendid, tils);
		}

		return ti;
	}
}
